package com.github.llyb120.tools.ctrl;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.github.llyb120.json.Obj;
import com.github.llyb120.report.Col;
import com.github.llyb120.report.Report;
import lombok.Data;
import org.beetl.sql.core.*;
import org.beetl.sql.core.db.MySqlStyle;
import org.beetl.sql.ext.DebugInterceptor;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import java.io.File;
import java.util.*;
import java.util.concurrent.ConcurrentSkipListMap;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

import static com.github.llyb120.json.Json.*;
import static org.springframework.http.HttpStatus.OK;

/**
 * @Author: Administrator
 * @Date: 8/25/2021 4:54 PM
 */
@RequestMapping("/api/tools/report-maker")
@Controller
public class ReportMakerCtrl {

    static ScriptEngine engine;
    static {
        ScriptEngineManager factory = new ScriptEngineManager();
        engine = factory.getEngineByName("groovy");
    }

    @Data
    static class Request{
        String code ;
        Ds dataSource;
        Map<String, String> params = new HashMap<>();
    }
    @Data
    static class Ds{
        String url;
        String driver;
        String username;
        String password;
    }

    @RequestMapping("make")
    public ResponseEntity make(
        @RequestBody Request request
    ) throws ScriptException {
        SQLManager sqlManager = sqlManager(request);
        Report report = (Report) engine.eval("import static com.github.llyb120.report.All.*\n" + request.getCode());
        HashMap<Object, Object> np = new HashMap<>();
        request.getParams().forEach((k,v) -> {
            if(k.equals("_start")){
                np.put("_start", Integer.parseInt(v));
            } else if(k.equals("_length")){
                np.put("_length", Integer.parseInt(v));
            } else {
                np.put(k,v);
            }
        });
        List<Map> res = sqlManager.execute(report.getDatasource(), Map.class, np);
        Map<String, String> alias = Collections.synchronizedMap(new LinkedHashMap<>());
        AtomicInteger i = new AtomicInteger();
        for (Col col : report.getCol()) {
            if(col.getEn() == null){
                col.setEn("calCol_" + (i.getAndIncrement()));
            }
            if(col.getCalculate() != null){
                int j = 0;
                for (Map item : res) {
                    Object value = item.get(col.getEn());
                    Object newValue= null;
                    switch (col.getCalculate().getMaximumNumberOfParameters()){
                        case 1:
                            newValue = col.getCalculate().call(value);
                            break;
                        case 2:
                            newValue = col.getCalculate().call(value,j);
                            break;
                        case 3:
                            newValue = col.getCalculate().call(value,j,res);
                            break;
                    }
                    item.put(col.getEn(), newValue);
                    j++;
                }
            }
            alias.put(col.getEn(), col.getCn());
        }

        if(res.isEmpty()){
            throw new RuntimeException();
        }
        File file = new File(System.getProperty("java.io.tmpdir"), IdUtil.objectId()+".xlsx");
        //通过工具类创建writer
        ExcelWriter writer = ExcelUtil.getWriter(file);
        //自定义标题别名
        i.set(0);
        alias.forEach(writer::addHeaderAlias);
        res = res.parallelStream()
            .map(e -> {
                Obj obj = o();
                for (String s : alias.keySet()) {
                    obj.put(s, e.get(s));
                }
                return obj;
            })
            .collect(Collectors.toList());
        writer.write(res);
        writer.flush();
        writer.close();
        byte[] bs = FileUtil.readBytes(file);
        file.delete();
        return new ResponseEntity(bs, OK);
//        System.out.println(123);
    }


    SQLManager sqlManager(Request request){
        ConnectionSource source = ConnectionSourceHelper.getSimple(request.getDataSource().getDriver(), request.getDataSource().getUrl(), request.getDataSource().getUsername(), request.getDataSource().getPassword());
//source是唯一必须的参数，其他参数都有默认值
        SQLManagerBuilder builder = new SQLManagerBuilder(source);
//设置NameConversion，这里数据库命名采用下划线风格，使用UnderlinedNameConversion
        builder.setNc(new DefaultNameConversion());
//设置一个拦截器，输出debug日志，包含了sql语句和执行参数，执行时间
        builder.setInters(new Interceptor[]{new DebugInterceptor()});
//设置数据库分隔，必须跟数据库一样
        builder.setDbStyle(new MySqlStyle());
        SQLManager sqlManager = builder.build();
        return sqlManager;
    }

}
